package secret

import (
	"encoding/base64"
	"encoding/json"
	"github.com/golang-jwt/jwt/v4"
	"strings"
	"time"
)

type CtpClaims struct {
	UserId   int64  `json:"id"`
	Nickname string `json:"nickname"`
	Email    string `json:"email"`
	jwt.RegisteredClaims
}

// GetJwtToken use msg to generate a new token
func GetJwtToken(secret, uuid, email, nickname string, userId int64, seconds time.Duration, audience ...string) (string, error) {
	now := time.Now()
	claims := CtpClaims{
		UserId:   userId,
		Nickname: nickname,
		Email:    email,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:   "CTP",
			Subject:  "CTP-JWT",
			Audience: audience,
			ExpiresAt: &jwt.NumericDate{
				Time: now.Add(seconds),
			},
			NotBefore: &jwt.NumericDate{
				Time: now,
			},
			IssuedAt: &jwt.NumericDate{
				Time: now,
			},
			ID: uuid,
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	return token.SignedString([]byte(secret))
}

// VerifyJwtToken return result of token's verify
func VerifyJwtToken(jwtToken, secret, level string) bool {
	token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
		return []byte(secret), nil
	})
	if err != nil || !token.Valid {
		return false
	}
	// 判断是否有相应权限
	claims, err := GetJwtClaims(jwtToken)
	if err != nil {
		return false
	}

	for _, audience := range claims.Audience {
		if audience == level {
			return true
		}
	}
	return false
}

// GetJwtClaims is a common method
func GetJwtClaims(jwtToken string) (*CtpClaims, error) {
	token := strings.Split(jwtToken, ".")[1]
	jsonStr, err := base64.RawStdEncoding.DecodeString(token)
	if err != nil {
		return nil, err
	}
	data := CtpClaims{}
	err = json.Unmarshal(jsonStr, &data)
	return &data, err
}
